package com.haowang.camera.manager;

import com.haowang.camera.util.CameraException;

import android.annotation.SuppressLint;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.util.Log;

public class CameraManager extends CameraManagerBase {

	private static final String TAG = CameraManager.class.getSimpleName();
	public static final int CAMERA_CLOSED = -1;
	public static final int CAMERA_OPENED = 0;
	public static final int PREVIEW_STARTED = 1;
	public static final int PREVIEW_STOPED = 2;
	public static final int IN_PROGRESS = 3;
	public static final int FOCUSING = 4;
	public static final int SWITCHING_CAMERA = 5;
	public static final int CAMERA_ERROR = 6;

	private static CameraManager sCameraManager = new CameraManager();
	private Camera mCameraDevice;

	private int mCameraId = -1;

	private int mCameraState = CAMERA_CLOSED;

	public int getCameraId() {
		return mCameraId;
	}

	public int getCameraState() {
		return mCameraState;
	}

	private CameraManager() {
		super();
	}

	@Override
	protected void reset() {
		releaseCamera();
		super.reset();
	}

	public synchronized static CameraManager instance() {
		return sCameraManager;
	}

	public synchronized Camera getCameraDevice(int cameraId)
			throws CameraException {
		if (mCameraDevice == null) {
			openCamera(cameraId);
		}
		return mCameraDevice;
	}

	@SuppressLint("NewApi")
	private synchronized void openCamera(int cameraId) throws CameraException {
		mCameraState = IN_PROGRESS;
		try {
			mCameraDevice = Camera.open(cameraId);
			if (mCameraDevice == null) {
				throw new CameraException();
			}
		} catch (Exception e) {
			Log.e(TAG, "open camera failed:" + e.getMessage());
			mCameraState = CAMERA_ERROR;
			throw new CameraException();
		}
		Log.i(TAG, "open camera success");
		mCameraId = cameraId;
		mCameraState = CAMERA_OPENED;
	}

	public synchronized void releaseCamera() {
		mCameraState = IN_PROGRESS;
		try {
			if (mCameraDevice != null) {
				mCameraDevice.release();
			}
		} catch (Exception e) {
			Log.e(TAG, "release camera occur error!:" + e.getMessage());
			// no need throw
		}
		mCameraDevice = null;
		mCameraState = CAMERA_CLOSED;
	}

	public synchronized void startPreview() throws CameraException {
		mCameraState = IN_PROGRESS;
		try {
			mCameraDevice.startPreview();
		} catch (Exception e) {
			Log.e(TAG, "start preview failed:" + e.getMessage());
			mCameraState = CAMERA_ERROR;
			throw new CameraException();
		}
		mCameraState = PREVIEW_STARTED;
	}

	public synchronized void stopPreview() throws CameraException {
		if (mCameraState != PREVIEW_STARTED) {
			return;
		}
		mCameraState = IN_PROGRESS;
		try {
			mCameraDevice.stopPreview();
		} catch (Exception e) {
			Log.e(TAG, "stop preview failed :" + e.getMessage());
			mCameraState = CAMERA_ERROR;
			throw new CameraException();
		}
		mCameraState = PREVIEW_STOPED;
	}

	public void takePicture(ShutterCallback shutter, PictureCallback raw,
			PictureCallback postview, PictureCallback jpeg) {
		if (mCameraState != PREVIEW_STARTED) {
			return;
		}
		mCameraState = IN_PROGRESS;
		mCameraDevice.takePicture(shutter, raw, postview, jpeg);
		mCameraState = PREVIEW_STOPED;
	}

}
